﻿using System;
using System.Management.Automation;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.PowerShell;
using Microsoft.SharePoint;

namespace MS.InformationManagement.DocumentIDServiceApp.Registration
{
    [Cmdlet(VerbsCommon.New, "NewDocumentIDServiceApplication",
        DefaultParameterSetName = NewDocumentIDServiceApplication.DefaultParameterSetName,
        SupportsShouldProcess = true)]
    [SPCmdlet(RequireLocalFarmExist = true, RequireUserFarmAdmin = true)]
    internal sealed class NewDocumentIDServiceApplication : SPCmdlet
    {
        private const string DefaultParameterSetName = "Default";
        private const string DatabaseServerParameterSetName = "DatabaseServer";
        private const string DefaultDatabaseName = "db_DocumentIDService";

        [Parameter(Mandatory = true, Position = 0)]
        [ValidateNotNullOrEmpty]
        public string Name { get; set; }

        [Parameter(Mandatory = true)]
        [ValidateNotNull]
        public SPIisWebServiceApplicationPoolPipeBind ApplicationPool { get; set; }

        [Parameter(Mandatory = false)]
        [ValidateNotNullOrEmpty]
        public string DatabaseName { get; set; }

        [Parameter(ParameterSetName = DatabaseServerParameterSetName, Mandatory = true)]
        [ValidateNotNullOrEmpty]
        public string DatabaseServer { get; set; }

        [Parameter(ParameterSetName = DatabaseServerParameterSetName, Mandatory = false)]
        [ValidateNotNullOrEmpty]
        public string FailoverDatabaseServer { get; set; }

        [Parameter(ParameterSetName = DatabaseServerParameterSetName, Mandatory = false)]
        [ValidateNotNull]
        public PSCredential DatabaseCredentials { get; set; }

        protected override void InternalProcessRecord()
        {
            // Ensure that the farm level required objects exist
            SPFarm farm = SPFarm.Local;
            if (null == farm)
            {
                ThrowTerminatingError(new InvalidOperationException("SharePoint server farm not found."),
                    ErrorCategory.ResourceUnavailable, this);
            }

            // Ensure that the sample web service exists

            DocumentIDService service = null;
            SPSecurity.RunWithElevatedPrivileges(delegate() {
                service = SPFarm.Local.Services.GetValue<DocumentIDService>("DocumentIDService");
            });
            
            if (service == null)
            {
                ThrowTerminatingError(new InvalidOperationException("DocumentID Service not found."),
                    ErrorCategory.ResourceUnavailable, this);
            }

            // Check for an existing sample web service application
            DocumentIDServiceApplication existingServiceApplication = service.Applications.GetValue<DocumentIDServiceApplication>();
            if (existingServiceApplication != null)
            {
                WriteError(new InvalidOperationException("DocumentID Service application exists."),
                    ErrorCategory.ResourceExists, existingServiceApplication);

                // Skip the current record
                SkipProcessCurrentRecord();
            }

            // Get a reference to the specified application pool
            SPIisWebServiceApplicationPool applicationPool = this.ApplicationPool.Read();
            if (null == applicationPool)
            {
                WriteError(new InvalidOperationException("The specified application pool could not be found."),
                    ErrorCategory.InvalidArgument, this);

                // Skip the current record.
                SkipProcessCurrentRecord();
            }

            if (String.IsNullOrEmpty(this.DatabaseName))
                this.DatabaseName = string.Format("{0}_{1}",NewDocumentIDServiceApplication.DefaultDatabaseName,Guid.NewGuid().ToString("N")) ;

            // Construct parameters for new database
            SPDatabaseParameters databaseParameters = SPDatabaseParameters.CreateParameters(
                this.DatabaseName,
                this.DatabaseServer,
                (null == this.DatabaseCredentials ? null : this.DatabaseCredentials.GetNetworkCredential()),
                this.FailoverDatabaseServer,
                SPDatabaseParameterOptions.ResolveNameConflict);

            if (ShouldProcess(this.Name))
            {
                // Create the sample application
                DocumentIDServiceApplication serviceApplication = DocumentIDServiceApplication.Create(
                    this.Name, service, applicationPool, databaseParameters);

                if (serviceApplication == null)
                {
                    WriteError(new NullReferenceException("DocumentIDServiceApplication"),
                        ErrorCategory.InvalidResult, this);
                }

                // Provision the sample application
                serviceApplication.Provision();

                // Write the new sample application to the pipeline
                WriteObject(serviceApplication);
            }
        }
    }
}
